package cn.funnymap.lgis.file;

import lombok.Getter;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * @author wenzf
 * @since 2025/8/25 10:28
 */
public class FileSize {
	//进制1024
	private static final int BASE = 1024;
	private static final int SCALE = 2;
	
	@Getter
	private long byteSize;
	@Getter
	private BigDecimal size;
	@Getter
	private Unit unit;
	@Getter
	private int scale;
	public FileSize(long byteSize, int scale) {
		fromSize(byteSize, scale);
	}
	public FileSize(long byteSize) {
		this(byteSize, -1);
	}
	
	public FileSize(BigDecimal size, Unit unit, int scale) {
		if(size == null) {
            size = BigDecimal.ZERO;
        }
		long byteSize = size.multiply(BigDecimal.valueOf(BASE).pow(unit.getCode())).longValue();
		fromSize(byteSize, scale);
	}
	public FileSize(double size, Unit unit) {
		this(BigDecimal.valueOf(size), unit, -1);
	}
	public FileSize(Object size, Unit unit) {
		this(toBigDecimal(size), unit, -1);
	}
	public static FileSize of(long byteSize, int scale) {
		return new FileSize(byteSize, scale);
	}
	public static FileSize of(long byteSize) {
		return new FileSize(byteSize);
	}
	public static FileSize of(BigDecimal size, Unit unit, int scale) {
		return new FileSize(size, unit, scale);
	}
	public static FileSize of(BigDecimal size, Unit unit) {
		return new FileSize(size, unit, -1);
	}
	
	/**
	 * 文件大小转换为BigDecimal
	 */
	private static BigDecimal toBigDecimal(Object value) {
		BigDecimal result = BigDecimal.ZERO;
		try {
			if (value != null) {
				if (value instanceof BigDecimal) {
					result = (BigDecimal) value;
				} else if (value instanceof Number) {
					result = BigDecimal.valueOf(((Number) value).doubleValue());
				} else if (value instanceof CharSequence) {
					result = new BigDecimal(value.toString().trim());
				}
			}
		} catch (Exception ignored) {}
		return result;
	}
	
	public void setScale(int scale) {
		BigDecimal sizeTemp = new BigDecimal(this.byteSize);
		BigDecimal divisor = BigDecimal.valueOf(Math.pow(BASE, unit.getCode()));
		if(scale < 0) {
			try{
				this.size = sizeTemp.divide(divisor);
			} catch(ArithmeticException e) {
				this.size = sizeTemp.divide(divisor, SCALE, RoundingMode.HALF_UP);
			}
		} else {
			this.size = sizeTemp.divide(divisor, scale, RoundingMode.HALF_UP);
		}
	}
	
	private void fromSize(long byteSize, int scale) {
		if (byteSize < 0) {
			throw new IllegalArgumentException("字节数不能为负数");
		}
		this.byteSize = byteSize;
		int unitCode = this.byteSize == 0 ? 0 : (int) (Math.log(byteSize) / Math.log(BASE));
		this.unit = Unit.fromCode(unitCode);
		setScale(scale);
	}
	public static String toSizeString(FileSize size) {
		if (size == null) {
			return "0 B";
		}
		return String.format("%s %s", size.getSize(), size.getUnit().getName());
	}
}
